package com.csnj.core.Srvs.SysManager.impl;

import com.csnj.common.constant.CommonConstants;
import com.csnj.common.jwt.JwtInfo;
import com.csnj.common.utils.TreeUtil;
import com.csnj.core.Srvs.SysManager.*;
import com.csnj.core.constant.CoreConstants;
import com.csnj.core.entity.SysElement;
import com.csnj.core.entity.SysMenu;
import com.csnj.core.entity.SysUser;
import com.csnj.core.entity.VO.FrontUser;
import com.csnj.core.entity.VO.MenuTree;
import com.csnj.core.entity.VO.PermissionInfo;
import com.csnj.core.exception.TokenInvalidException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created by xiabin on 2018/11/22.
 */
@Service
public class PermissionSrvsImpl implements PermissionSrvs {
    @Autowired
    AuthSrvs authSrvs;
    @Autowired
    SysMenuSrvs sysMenuSrvs;
    @Autowired
    SysUserSrvs userSrvs;
    @Autowired
    ElementSrvs elementSrvs;

    @Override
    public List<MenuTree> getMenusByToken(String token) throws TokenInvalidException {
        JwtInfo info = authSrvs.validate(token);
        Integer uid = Integer.valueOf(info.getUserId());
        List<SysMenu> menus = sysMenuSrvs.getUserAuthorityMenuByUserId(uid);
        return genMenuTree(menus, CoreConstants.ROOT);
    }

    public List<PermissionInfo> getPermissionByUid(Integer userId) {
        List<SysMenu> menus = sysMenuSrvs.getUserAuthorityMenuByUserId(userId);
        List<PermissionInfo> result = new ArrayList<PermissionInfo>();
        PermissionInfo info = null;
        menu2permission(menus, result);
        List<SysElement> elements = elementSrvs.getAuthorityElementByUserId(userId);
        element2permission(result, elements);
        return result;
    }

    @Override
    public FrontUser getUserInfo(String token) throws TokenInvalidException {
        JwtInfo info = authSrvs.validate(token);
        Integer uid = Integer.valueOf(info.getUserId());
        SysUser user = userSrvs.selectById(uid);
        FrontUser frontUser = new FrontUser();
        BeanUtils.copyProperties(user, frontUser);
        List<PermissionInfo> permissionInfos = this.getPermissionByUid(uid);
        Stream<PermissionInfo> menus = permissionInfos.parallelStream().filter((permission) -> permission.getType().equals(CommonConstants.RESOURCE_TYPE_MENU));
        frontUser.setMenus(menus.collect(Collectors.toList()));
        Stream<PermissionInfo> elements = permissionInfos.parallelStream().filter((permission) -> !permission.getType().equals(CommonConstants.RESOURCE_TYPE_MENU));
        frontUser.setElements(elements.collect(Collectors.toList()));
        return frontUser;
    }

    private List<MenuTree> genMenuTree(List<SysMenu> menus, int root) {
        List<MenuTree> trees = new ArrayList<MenuTree>();
        MenuTree node = null;
        for (SysMenu menu : menus) {
            node = new MenuTree();
            BeanUtils.copyProperties(menu, node);
            trees.add(node);
        }
        return TreeUtil.bulid(trees, root);
    }

    private void menu2permission(List<SysMenu> menus, List<PermissionInfo> result) {
        PermissionInfo info;
        for (SysMenu menu : menus) {
            if (StringUtils.isBlank(menu.getHref())) {
                menu.setHref("/" + menu.getCode());
            }
            info = new PermissionInfo();
            info.setCode(menu.getCode());
            info.setType(CoreConstants.RESOURCE_TYPE_MENU);
            info.setName(CoreConstants.RESOURCE_ACTION_VISIT);
            String uri = menu.getHref();
            if (!uri.startsWith("/")) {
                uri = "/" + uri;
            }
            info.setUri(uri);
            info.setMethod(CoreConstants.RESOURCE_REQUEST_METHOD_GET);
            result.add(info
            );
            info.setMenu(menu.getTitle());
        }
    }

    private void element2permission(List<PermissionInfo> result, List<SysElement> elements) {
        PermissionInfo info;
        for (SysElement element : elements) {
            info = new PermissionInfo();
            info.setCode(element.getCode());
            info.setType(element.getType());
            info.setUri(element.getUri());
            info.setMethod(element.getMethod());
            info.setName(element.getName());
            info.setMenu(element.getMenuId().toString());
            result.add(info);
        }
    }
}
